<template>
  <div class="dict-select-dlg">
    <el-row type="flex" justify="space-between" align="middle" style="margin-bottom: 16px">
      <div>
        <el-input
          v-if="Array.isArray(filterFields) && filterFields.length > 0"
          v-model="searchString"
          placeholder="请输入模糊查询条件"
          :clearable="true"
          size="default"
          style="width: 300px"
        />
      </div>
      <el-button type="primary" size="default" @click="onSubmit"> 确定 </el-button>
    </el-row>
    <div class="table-box">
      <vxe-table
        ref="table"
        :row-id="dialogParams.props.value"
        :tree-config="treeConfig"
        :data="filteredDataList"
        show-overflow="title"
        show-header-overflow="title"
        height="100%"
        :row-config="{ height: 50, isHover: true }"
        :virtual-y-config="{ enabled: true, gt: 20 }"
        :radio-config="{ highlight: true }"
        :checkbox-config="getSelectConfig"
        @radio-change="onSelectChange"
        @checkbox-all="onSelectChange"
        @checkbox-change="onSelectChange"
        @cell-click="onCellClick"
      >
        <vxe-column
          :type="dialogParams.multiple ? 'checkbox' : 'radio'"
          :width="treeConfig != null ? 90 : 50"
          :tree-node="treeConfig != null"
        />
        <vxe-column
          v-for="tableColumn in tableColumnList"
          :key="tableColumn.field"
          :title="tableColumn.title"
          :field="tableColumn.field"
        >
          <template #default="{ row }">
            <span>{{ row[tableColumn.field + '_dictmap_name'] || row[tableColumn.field] }}</span>
          </template>
        </vxe-column>
      </vxe-table>
    </div>
  </div>
</template>

<script setup lang="ts">
import { VxeTable, VxeColumn, VxeTableDefines } from 'vxe-table';
import { treeDataTranslate, findItemFromList } from '@/common/utils';
import { OnlineOperationController } from '@/api/online';
import { ANY_OBJECT } from '@/types/generic';
import { DialogProp } from '@/components/Dialog/types';
import { useTable } from '@/common/hooks/useTable';
import { TableOptions } from '@/common/types/pagination';
import { useThirdParty } from '@/components/thirdParty/hooks';
import { ThirdProps } from '@/components/thirdParty/types';

interface IProps extends ThirdProps {
  value?: string | number | ANY_OBJECT[];
  dictInfo?: ANY_OBJECT;
  multiple?: boolean;
  props?: {
    label: string;
    value: string;
  };
  ignoreDictKeys?: string[];
  ignoreSelect?: boolean;
  // 当使用Dialog.show弹出组件时，须定义该prop属性，以便对dialog进行回调
  dialog?: DialogProp<ANY_OBJECT>;
}

const props = withDefaults(defineProps<IProps>(), {});
const { thirdParams, onCloseThirdDialog } = useThirdParty(props);

const table = ref();
const searchString = ref('');
const dialogSelectItems = ref<ANY_OBJECT | ANY_OBJECT[]>();
const dialogParams = computed(() => {
  return {
    value: props.value || thirdParams.value,
    props:
      props.props || thirdParams.value.props == null ? props.props : thirdParams.value.props || {},
    dictInfo: props.dictInfo || thirdParams.dictInfo,
    ignoreDictKeys: props.ignoreDictKeys || thirdParams.value.ignoreDictKeys,
    ignoreSelect: props.ignoreSelect || thirdParams.value.ignoreSelect,
    multiple:
      props.multiple || thirdParams.value.multiple == null
        ? props.multiple
        : thirdParams.value.multiple,
  };
});

const tableColumnList = computed(() => {
  if (dialogParams.value.dictInfo == null) return [];
  let dialogSetting = dialogParams.value.dictInfo.dialogSetting;
  let tableColumnList = [];
  if (dialogSetting != null && dialogSetting.tableColumnList != null) {
    Object.keys(dialogSetting.tableColumnList).forEach(key => {
      let item = dialogSetting.tableColumnList[key];
      if (item != null && item.isShow) {
        tableColumnList.push({
          title: item.columnComment,
          field: key,
          columnName: key,
          dictId: item.dictId,
        });
      }
    });
  }
  return tableColumnList;
});

const getSelectConfig = computed(() => {
  let selectRowKeys = dialogParams.value.multiple
    ? (dialogSelectItems.value || []).map(item => {
        return item[dialogParams.value.props.value];
      })
    : (dialogSelectItems.value || {})[dialogParams.value.props.value];
  return {
    highlight: true,
    checkStrictly: true,
    checkRowKeys: dialogParams.value.multiple ? selectRowKeys : undefined,
    checkRowKey: dialogParams.value.multiple ? undefined : selectRowKeys,
    showHeader: false,
  };
});

const dialogSetting = computed(() => {
  if (dialogParams.value.dictInfo == null) return null;
  let dialogSetting = dialogParams.value.dictInfo.dialogSetting;
  if (dialogSetting == null) return null;
  return dialogSetting;
});

const filterFields = computed(() => {
  if (dialogSetting.value == null) return [];
  return dialogSetting.value.filterFields || [];
});

const filteredDataList = computed(() => {
  if (dialogParams.value.dictInfo == null) return [];
  if (dictTableWidget == null || dictTableWidget.dataList == null) return [];
  if (searchString.value == null || searchString.value === '') return dictTableWidget.dataList;
  if (!Array.isArray(filterFields.value) || filterFields.value.length === 0) {
    return dictTableWidget.dataList;
  }
  return dictTableWidget.dataList.filter(data => {
    let isMatch = false;
    for (let i = 0; i < filterFields.value.length; i++) {
      let field = filterFields.value[i];
      let fieldData = data[field + '_dictmap_name'] || data[field];
      if (fieldData != null && fieldData.toString().indexOf(searchString.value) >= 0) {
        isMatch = true;
        break;
      }
    }
    return isMatch;
  });
});

const treeConfig = computed(() => {
  if (dialogParams.value.dictInfo == null || !dialogParams.value.dictInfo.treeFlag) return null;
  let temp = {
    transform: true,
    rowField: dialogParams.value.props.value,
    parentField: dialogParams.value.dictInfo.parentKeyColumnName,
    childrenField: 'children',
    expandAll: true,
  };
  return temp;
});

const onCellClick = ({ row }: { row: ANY_OBJECT }) => {
  if (dialogParams.value.multiple) {
    // 多选模式：切换当前行的选中状态
    const isChecked = table.value.isCheckedByCheckboxRow(row);
    table.value.setCheckboxRow(row, !isChecked);

    if (!dialogSelectItems.value) dialogSelectItems.value = [];
    if (!isChecked) {
      (dialogSelectItems.value as ANY_OBJECT[]).push(row);
    } else {
      dialogSelectItems.value = (dialogSelectItems.value as ANY_OBJECT[]).filter(
        (item: ANY_OBJECT) =>
          item[dialogParams.value.props.value] !== row[dialogParams.value.props.value],
      );
    }
  } else {
    // 单选模式
    table.value.setRadioRow(row);
    dialogSelectItems.value = row;
  }
};

const setTableSelectRow = () => {
  if (table.value == null || !Array.isArray(dictTableWidget.dataList)) return;
  setTimeout(() => {
    table.value.clearRadioRow();
    table.value.clearCheckboxRow();
    if (dialogParams.value.multiple) {
      table.value.setCheckboxRow(
        dictTableWidget.dataList.filter(item => {
          return (
            findItemFromList(
              dialogSelectItems.value,
              item[dialogParams.value.props.value],
              dialogParams.value.props.value,
            ) != null
          );
        }),
        true,
      );
    } else {
      let selectRow = findItemFromList(
        dictTableWidget.dataList,
        (dialogSelectItems.value || {})[dialogParams.value.props.value],
        dialogParams.value.props.value,
      );
      table.value.setRadioRow(selectRow);
    }
  }, 50);
};

const loadDictTableData = params => {
  if (params == null) params = {};
  params = {
    ...params,
    dictId: dialogParams.value.dictInfo.dictId,
    dictRelations: tableColumnList.value
      .map(item => {
        return {
          dataIdColumn: item.columnName,
          dictId: item.dictId === '' || item.dictId == null ? undefined : item.dictId,
        };
      })
      .filter(item => {
        return item.dictId != null;
      }),
  };
  // 添加字典排除数据（脚本模式）
  if (
    dialogParams.value.multiple &&
    dialogParams.value.ignoreDictKeys &&
    dialogParams.value.ignoreDictKeys.length > 0
  ) {
    params.ignoreDictKeys = dialogParams.value.ignoreDictKeys;
  }
  // 添加字典排除数据（组件模式）
  if (
    dialogParams.value.multiple &&
    dialogParams.value.ignoreSelect &&
    Array.isArray(dialogParams.value.value) &&
    dialogParams.value.value.length > 0
  ) {
    const keyName = dialogParams.value.dictInfo.keyColumnName;
    const ignoreDictKeys = dialogParams.value.value.map(item => {
      return item[keyName];
    });
    params.ignoreDictKeys = ignoreDictKeys;
  }
  return new Promise((resolve, reject) => {
    OnlineOperationController.listTableDict(params)
      .then(res => {
        (res.data || []).forEach(item => {
          Object.keys(item).forEach(key => {
            if (item[key + 'DictMap'] != null) {
              item[key + '_dictmap_name'] = item[key + 'DictMap'].name || item[key];
            }
            if (Array.isArray(item[key + 'DictMapList'])) {
              item[key + '_dictmap_name'] = item[key + 'DictMapList']
                .map(dictItem => {
                  return dictItem.name;
                })
                .join(',');
            }
          });
        });
        resolve({
          dataList: res.data,
          totalCount: (res.data || []).length,
        });
        nextTick(() => {
          setTableSelectRow();
        });
      })
      .catch(e => {
        reject(e);
      });
  });
};

const loadDictTableDataVerify = () => {
  return true;
};

const tableOptions: TableOptions<ANY_OBJECT> = {
  loadTableData: loadDictTableData,
  verifyTableParameter: loadDictTableDataVerify,
  paged: false,
};
const dictTableWidget = reactive(useTable(tableOptions));

const onSubmit = () => {
  if (props.dialog) {
    props.dialog.submit(dialogSelectItems.value);
  } else {
    onCloseThirdDialog(true, dialogParams.value.value, dialogSelectItems.value);
  }
};

const refreshDictTableData = () => {
  if (dialogParams.value.dictInfo == null) return;
  dictTableWidget.refreshTable(true, 1);
};

const onSelectChange = ({
  checked,
  row,
}: VxeTableDefines.RadioChangeEventParams | VxeTableDefines.CheckboxAllEventParams) => {
  if (dialogParams.value.multiple) {
    if (row == null) {
      dialogSelectItems.value = [];
      if (checked) {
        dialogSelectItems.value = dictTableWidget.dataList;
      }
    } else {
      if (dialogSelectItems.value == null) dialogSelectItems.value = [];
      if (checked) {
        dialogSelectItems.value.push(row);
      } else {
        dialogSelectItems.value = dialogSelectItems.value.filter(item => {
          return item[dialogParams.value.props.value] !== row[dialogParams.value.props.value];
        });
      }
    }
  } else {
    dialogSelectItems.value = row;
  }
};

onMounted(() => {
  if (Array.isArray(dialogParams.value.value) && dialogParams.value.value.length > 0) {
    if (dialogParams.value.multiple) {
      dialogSelectItems.value = dialogParams.value.value.map(item => {
        return {
          ...item,
        };
      });
    } else {
      console.log('单选', dialogParams.value.value);
      dialogSelectItems.value = {
        ...dialogParams.value.value[0],
      };
    }
  }
  refreshDictTableData();
});
</script>
<style scoped>
.dict-select-dlg {
  display: flex;
  flex-direction: column;
  height: 100%;
}
.table-box {
  flex: 1;
}
</style>
